package de.servicezombie.lang;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReflectionUtils {

	private static final Logger log = LoggerFactory.getLogger(ReflectionUtils.class);
	
	public static Field[] getAllAnnotatedFields(Class<?> fromClass, Class<? extends Annotation> annotationType) {

		List<Field> fields = new ArrayList<Field>();
		Class<?> type = fromClass;

		while (!type.equals(Object.class)) {
			Field[] declaredFields = type.getDeclaredFields();

			if (declaredFields != null) {
				for (Field f : declaredFields) {
					Object annotation = f.getAnnotation(annotationType);
					if (annotation != null) {
						fields.add(f);
					}
				}
			}

			type = type.getSuperclass();
		}

		Field[] fieldsArray = new Field[fields.size()];
		fieldsArray = fields.toArray(fieldsArray);
		return fieldsArray;
	}

	
	public static void cloneByAnnotatedField(Object source, Object target, Class<? extends Annotation> annotationClass) {

		Class<?> clazz = source.getClass();

		while (clazz != Object.class) {

			Field[] allFields = clazz.getDeclaredFields();

			for (Field f : allFields) {
				Annotation annotation = f.getAnnotation(annotationClass);
				
				if (annotation != null) {
					
					if (log.isDebugEnabled()) {
						log.debug("clone: copy field " + f.getName());
					}
				
					
					if (!f.isAccessible()) {
						f.setAccessible(true);
					}

					try {
						final Object value = f.get(source);						
						f.set(target, value);
					}
					catch (IllegalAccessException e) {
						ExceptionUtils.wrapUnexpectedException(e);
					}
				}
			}

			clazz = clazz.getSuperclass();
		}
	} 
}
